/////////////////////////////////////////////////////////////////////////////////////////////////////
// 
// NHP协议的浙里办小程序JS SDK
// 版本号：v3.4 (发布于2024-03-12）
// 关于NHP协议的定义，请参见中国计算机学会CCF的《零信任网络隐身协议规范》
// 反馈意见请发送至： zsec@z-sec.net，感谢您的参与支持！
//
/////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// 常量定义
////////////////////////////////////////////////////////////////////////////

// 全局开关
var DEBUG_MODE = 0; // 是否开启Debug模式，发布时应该为0

// 错误码定义
const ERR_SUCCESS = 0;        // 成功
const ERR_EXIT    = 1;        // 立即退出
const ERR_HTTPREQ = -1;       // 对服务器的HTTP请求失败为-1
const ERR_INVALIDPARAM = -2;  // 错误的函数参数
const MSG_INVALIDPARAM = '[NHP] Invalid Parameters'; //ERR_INVALIDPARAM对应的错误消息

// Header定义
const NHP_HEADER = 'X-NHP-Token';    // NHP Token
// NHP SDK版本
const NHP_VERSION = "3.4"; // NHP SDK Version

////////////////////////////////////////////////////////////////////////////
// 内部函数
////////////////////////////////////////////////////////////////////////////

// Print debug log
function debugLog(msg) {
  if (DEBUG_MODE) { // 调试模式下，才打印日志
    console.info(msg);
  }
}

////////////////////////////////////////////////////////////////////////////
// 内部函数，用于敲门
////////////////////////////////////////////////////////////////////////////
function nhpKnockDoor(appToken, nhpServer, aspId, resId, callback) {
    // 打印调试信息
    debugLog(
        "[NHP] nhpKnockDoor: appToken=" + appToken +
        "; nhpServer=" + nhpServer +
        "; aspId=" + aspId +
        "; resId=" + resId
    );

    // 参数校验
    if (!appToken || !nhpServer || !aspId || !resId || !callback) {
        debugLog(MSG_INVALIDPARAM);
        callback({
            errCode: ERR_INVALIDPARAM, // 输入参数错误，程序中断
            errMsg:  MSG_INVALIDPARAM
        });
        return;
    }
  
    // NHP服务器请求URL
    const nhpURL = "https://" + nhpServer + 
        "/plugins/" + encodeURIComponent(aspId) +
        "?resid=" + encodeURIComponent(resId) +
        "&token=" + encodeURIComponent(appToken) + 
        "&action=valid"; 
        
    debugLog("[NHP] fetch: " + nhpURL);

    // 向NHP服务器发起AJAX请求
    fetch(nhpURL, {
        method: 'GET',
        headers: {
            'X-NHP-Ver': NHP_VERSION
        },
    })
    .then((response) => {
        debugLog(response);
        if (!response.ok) {
            throw new Error(`[NHP] HTTP error: ${response.status}`);
        }
        return response.json();
    })
    .then((json) => {
        // 对NHP服务器的HTTP请求成功，返回给调用者
        callback(json);
    })
    .catch((err) => {
        // 对NHP服务器的HTTP请求失败，需要提示调用者
        callback({
            errCode: ERR_HTTPREQ, // 对NHP服务器的HTTP请求失败为-2；
            errMsg: err.message
        });   
    }); 
} //function nhpKnockDoor

/**
 * debug模式开关函数
 *
 * @param {number} debugMode 0：关闭debug模式；1：打开debug模式；
 *
 */
function debug(debugMode) {
    DEBUG_MODE = debugMode;
} // function debug

/**
 * login登录函数。调用login函数，将使用单点登录票据ticketId换取用户身份token。
 *
 * @param {string} ticketId 浙里办单点登录的用户票据信息，通过调用ZWJSBridge.ssoTicket()获得。
 * @param {string} nhpServer NHP服务器地址，可以为域名或者IP地址，例如"nhp.huzhou.gov.cn"。
 * @param {string} aspId 身份验证授权服务提供商ASP的ID：浙里办是"zlb"，浙政钉是"zzd"。
 * @param {string} resId 资源ID字符串，一般为浙里办的AppId，如"2001832595"。
 *
 * @return {Promise} 登录结果的Promise对象。
 */
function login(ticketId, nhpServer, aspId, resId) {
    // 打印调试信息
    debugLog(
        "[NHP] login: ticketId=" + ticketId +
        "; nhpServer=" + nhpServer + 
        "; aspId=" + aspId + 
        "; resId=" + resId
    );

    return new Promise(function(resolve, reject) {
        // 参数校验
        if (!ticketId || !nhpServer || !aspId || !resId) {
            debugLog("ERR_INVALIDPARAM");
            reject({
                errCode: ERR_INVALIDPARAM, // 输入参数错误，程序中断
                errMsg: MSG_INVALIDPARAM
            });
        }

        // NHP服务器请求nhpURL
        const nhpURL = "https://" + nhpServer + 
            "/plugins/" + encodeURIComponent(aspId) + 
            "?resid=" + encodeURIComponent(resId) + 
            "&ticketid=" + encodeURIComponent(ticketId) + 
            "&action=valid";
        debugLog("[NHP] fetch: " + nhpURL);

        // 向NHP服务器发起AJAX请求
        fetch(nhpURL, {
            method: 'GET',
            headers: {
                'X-NHP-Ver': NHP_VERSION
            },
        })
        .then((response) => {
            debugLog(response);
            if (!response.ok) {
                throw new Error(`HTTP error: ${response.status}`);
            }
            return response.json();
        })
        .then((json) => {
            // 对NHP服务器的HTTP请求成功，返回JSON对象
            resolve(json);
        })
        .catch((err) => {
            // 对NHP服务器的HTTP请求失败，需要提示调用者
            reject({
                errCode: ERR_HTTPREQ, // 对NHP服务器的HTTP请求失败为-2；
                errMsg: err.message
            });
        });
    }); //return new Promise(function(resolve, reject) {
} // function login

/**
 * NHP协议开启敲门函数，调用open函数将开启以interval间隔为时长的连续敲门。
 *
 * @param {string} appToken 浙里办客户端的用户身份token，用户向浙里办服务器验证用户身份。
 * @param {number} interval 敲门间隔时长，以毫秒ms为单位，例如20*1000 表示20秒。
 * @param {string} nhpServer NHP服务器地址，可以为域名或者IP地址，例如"nhp.huzhou.gov.cn"。
 * @param {string} aspId 身份验证授权服务提供商ASP的ID：浙里办是"zlb"，浙政钉是"zzd"。
 * @param {string} resId 资源ID字符串，一般为浙里办的AppId，如"2001832595"。
 * @param {function} callback 回调函数，callback(msg)，msg为NHP服务器返回的消息。
 *
 * @return {number} NHP的敲门计时器ID，即timerID，可以通过调用close(timerID)来关闭敲门。
 */
function open(appToken, interval, nhpServer, aspId, resId, callback) {
    debugLog(
        "[NHP] open: appToken=" + appToken + 
        "; interval=" + interval + 
        "; nhpServer=" + nhpServer + 
        "; aspId=" + aspId + 
        "; resId=" + resId
    );
  
    // 马上执行一次敲门函数
    nhpKnockDoor(
        appToken,     // 浙里办的用户身份Token，用于验证用户身份
        nhpServer,    // NHP 服务器地址，例如"nhp.huzhou.gov.cn"
        aspId,        // 身份验证授权服务提供商ASP的ID
        resId,        // 资源ID字符串，一般为浙里办的AppId，如"2001832595"
        callback      // 回调函数，callback(msg)，msg为NHP服务器返回的消息
    );

    // 每隔interval秒执行一次 敲门函数
    const timerID = setInterval(
        function() {
            nhpKnockDoor(appToken, nhpServer, aspId, resId, callback); // 敲门函数
        },
        interval      // 敲门间隔
    );
    return timerID;
} // function open

/**
 * NHP协议关闭敲门函数。
 *
 * @param {number} timerID NHP的敲门计时器ID。
 */
function close(timerID) {
    debugLog("[NHP] close: timerID=" + timerID); 
    if (timerID) {
        clearInterval(timerID);
    }
} //function close

/**
 * NHP协议开启敲门函数open的Promise实现。
 *
 * @param {string} appToken 浙里办客户端的用户身份token，用户向浙里办服务器验证用户身份。
 * @param {number} interval 敲门间隔时长，以毫秒ms为单位，例如20*1000 表示20秒。
 * @param {string} nhpServer NHP服务器地址，可以为域名或者IP地址，例如"nhp.huzhou.gov.cn"。
 * @param {string} aspId 身份授权服务提供商ASP的ID，例如 "zzd"表示浙政钉、"zlb"表示浙里办。
 * @param {string} resId 资源ID字符串，一般为浙里办的AppId，如"2001832595"。
 * @return {Promise} 开门结果的Promise对象。
 */
function openPromise(appToken, interval, nhpServer, aspId, resId) {
    debugLog(
        "[NHP] openPromise: appToken=" + appToken + 
        "; interval=" + interval + 
        "; nhpServer=" + nhpServer + 
        "; aspId=" + aspId + 
        "; resId=" + resId
      );
    
      return new Promise((resolve, reject) => {
        open(appToken, interval, nhpServer, aspId, resId, function(msg) {
          if (msg.errCode == ERR_SUCCESS) {
            resolve(msg);
          } else {
            reject(msg);
          }
        });
      });    
}

////////////////////////////////////////////////////////////////////////////
// 本JS模块对外暴露的函数和常量
////////////////////////////////////////////////////////////////////////////
export default {
    login: login,   // 单点登录
    open: open,     // 开启敲门
    openPromise : openPromise, // 开启敲门的Promise实现
    close: close,   // 关闭敲门
    debug: debug,   // 开启/关闭Debug模式
    httpHeader: NHP_HEADER, // NHP HTTP Header name
    ERR_CODE: {     // 错误码常量
        success: ERR_SUCCESS,
        exit: ERR_EXIT,
        httpReq: ERR_HTTPREQ,
        invalidParam: ERR_INVALIDPARAM
    }
};
